package com.lz.spring;

import com.lz.spring.annotation.Autowire;
import com.lz.spring.annotation.Bean;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * <pre>
 * @描述：
 * @作者：lizhao
 * @创建时间： 2024/9/25 下午4:47
 * </pre>
 **/
public class Context {
    private Config config;
    private Map<Class<?>, Method> beanDefinitionsMap;
    private Map<Class<?>, Object> beanFactory;

    public void init() {
        this.beanDefinitionsMap = new HashMap<>();
        this.beanFactory = new HashMap<>();
        Class<Config> configClazz = Config.class;
        Method[] methods = configClazz.getDeclaredMethods();
        for (Method method : methods) {
            if (method.getAnnotation(Bean.class) != null) {
                System.out.println(method.getName());
                this.beanDefinitionsMap.put(method.getReturnType(), method);
            }
        }
        try {
            config = configClazz.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public Object getBean(Class<?> clazz) throws InvocationTargetException, IllegalAccessException {
        if (beanFactory.containsKey(clazz)) {
            return beanFactory.get(clazz);
        }
        if (beanDefinitionsMap.containsKey(clazz)) {
            Method method = beanDefinitionsMap.get(clazz);
            Object invoke = method.invoke(config);
            beanFactory.put(clazz, invoke);
            return invoke;
        }
        return null;
    }

    public Object demo(Class<?> clazz) throws InvocationTargetException, InstantiationException, IllegalAccessException {
        Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
        for (Constructor<?> constructor : declaredConstructors) {
            if (constructor.getAnnotation(Autowire.class) != null) {
                Class<?>[] parameterTypes = constructor.getParameterTypes();
                Object[] objects = new Object[parameterTypes.length];
                for (int i = 0; i < parameterTypes.length; i++) {
                    objects[i] = beanFactory.get(parameterTypes[i]);
                }
                Object o = constructor.newInstance(objects);
                beanFactory.put(clazz, o);
                return o;
            }
        }
        return null;
    }

}
